#define _CRT_SECURE_NO_WARNINGS
#include"FileIO.h"

/**
 * 初始化系统数据
 *
 * @return 初始化的系统数据结构指针
 */
SystemData* initSystem() {
    // 分配系统数据结构
    SystemData* data = (SystemData*)malloc(sizeof(SystemData));
    if (data == NULL) {
        fprintf(stderr, "系统初始化失败：内存分配错误\n");
        return NULL;
    }

    // 初始化各个链表为空
    data->userList = NULL;
    data->packageList = NULL;
    data->packageTail = NULL;
    data->shelfList = NULL;
    data->shelfTail = NULL;
    data->logList = NULL;
    data->notificationList = NULL;

    // 设置角色默认权限
    data->rolePermissions[USER_STUDENT - 1] = PERM_PACKAGE_QUERY;  // 普通用户(学生)
    data->rolePermissions[USER_VIP - 1] = PERM_PACKAGE_QUERY;      // VIP用户
    data->rolePermissions[USER_COURIER - 1] = PERM_PACKAGE_QUERY | PERM_PACKAGE_ADD;  // 快递员
    data->rolePermissions[USER_STAFF - 1] = PERM_PACKAGE_QUERY | PERM_PACKAGE_ADD | PERM_PACKAGE_PICKUP | PERM_SHELF_MGMT;  // 驿站工作人员
    data->rolePermissions[USER_ADMIN - 1] = PERM_ALL;  // 系统管理员

    // 创建数据目录和空文件（如果不存在）
    ErrorCode result = createDataDirectoryIfNotExists();
    if (result != OK) {
        fprintf(stderr, "创建数据目录失败，错误码: %d\n", result);
        free(data);
        return NULL;
    }

    // 创建空的CSV文件（如果不存在）
    const char* files[] = {
        USERS_FILE,
        PACKAGES_FILE,
        SHELVES_FILE,
        LOGS_FILE,
        NOTIFICATIONS_FILE
    };

    for (int i = 0; i < sizeof(files) / sizeof(files[0]); i++) {
        result = createEmptyFileIfNotExists(files[i]);
        if (result != OK) {
            fprintf(stderr, "创建文件 %s 失败，错误码: %d\n", files[i], result);
            free(data);
            return NULL;
        }
    }

    // 如果没有用户，创建默认管理员账户
    FILE* usersFile = fopen(USERS_FILE, "r");
    if (usersFile) {
        char buffer[1024];
        // 检查文件是否只有标题行或为空
        int lineCount = 0;
        while (fgets(buffer, sizeof(buffer), usersFile) != NULL && lineCount < 2) {
            lineCount++;
        }
        fclose(usersFile);

        // 如果文件为空或只有标题行，创建默认管理员
        if (lineCount <= 1) {
            User* admin = (User*)malloc(sizeof(User));
            if (admin == NULL) {
                fprintf(stderr, "创建默认管理员账户失败：内存分配错误\n");
                free(data);
                return NULL;
            }

            strcpy(admin->username, "admin");
            strcpy(admin->password, "admin123");
            strcpy(admin->phone, "10000000000");
            strcpy(admin->address, "系统管理员");
            admin->type = USER_ADMIN;
            admin->vipLevel = 0;
            admin->permissions = PERM_ALL;
            admin->next = NULL;

            data->userList = admin;

            // 保存默认用户
            saveUsersToFile(data, USERS_FILE);
        }
    }

    // 记录系统启动日志
    Log* startupLog = (Log*)malloc(sizeof(Log));
    if (startupLog != NULL) {
        strcpy(startupLog->username, "SYSTEM");
        strcpy(startupLog->operation, "系统启动");
        startupLog->operationTime = time(NULL);
        startupLog->next = NULL;

        data->logList = startupLog;
    }

    return data;
}

/**
 * 从文件加载系统数据
 *
 * @param data 系统数据结构指针
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode loadSystemData(SystemData* data) {
    if (data == NULL) {
        return ERR_INVALID_PARAM;
    }

    // 记录开始加载的时间
    time_t startTime = time(NULL);

    // 逐个加载数据文件
    ErrorCode result;

    // 1. 加载用户数据
    result = loadUsersFromFile(data, USERS_FILE);
    if (result != OK) {
        fprintf(stderr, "加载用户数据失败，错误码: %d\n", result);
        return result;
    }

    // 2. 加载货架数据
    result = loadShelvesFromFile(data, SHELVES_FILE);
    if (result != OK) {
        fprintf(stderr, "加载货架数据失败，错误码: %d\n", result);
        return result;
    }

    // 3. 加载包裹数据
    result = loadPackagesFromFile(data, PACKAGES_FILE);
    if (result != OK) {
        fprintf(stderr, "加载包裹数据失败，错误码: %d\n", result);
        return result;
    }

    // 4. 加载通知数据
    result = loadNotificationsFromFile(data, NOTIFICATIONS_FILE);
    if (result != OK) {
        fprintf(stderr, "加载通知数据失败，错误码: %d\n", result);
        return result;
    }

    // 5. 加载日志数据
    result = loadLogsFromFile(data, LOGS_FILE);
    if (result != OK) {
        fprintf(stderr, "加载日志数据失败，错误码: %d\n", result);
        return result;
    }

    // 记录数据加载操作
    Log* loadLog = (Log*)malloc(sizeof(Log));
    if (loadLog != NULL) {
        strcpy(loadLog->username, "SYSTEM");

        time_t endTime = time(NULL);
        double elapsed = difftime(endTime, startTime);

        snprintf(loadLog->operation, MAX_DESCRIPTION_LEN,
            "系统数据加载完成，耗时: %.2f 秒", elapsed);

        loadLog->operationTime = endTime;
        loadLog->next = data->logList;
        data->logList = loadLog;
    }

    return OK;
}

/**
 * 将系统数据保存到文件
 *
 * @param data 系统数据结构指针
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode saveSystemData(SystemData* data) {
    if (data == NULL) {
        return ERR_INVALID_PARAM;
    }

    // 记录开始保存的时间
    time_t startTime = time(NULL);

    // 确保数据目录存在
    ErrorCode result = createDataDirectoryIfNotExists();
    if (result != OK) {
        fprintf(stderr, "创建数据目录失败，错误码: %d\n", result);
        return result;
    }

    // 逐个保存数据文件

    // 1. 保存用户数据
    result = saveUsersToFile(data, USERS_FILE);
    if (result != OK) {
        fprintf(stderr, "保存用户数据失败，错误码: %d\n", result);
        return result;
    }

    // 2. 保存包裹数据
    result = savePackagesToFile(data, PACKAGES_FILE);
    if (result != OK) {
        fprintf(stderr, "保存包裹数据失败，错误码: %d\n", result);
        return result;
    }

    // 3. 保存货架数据
    result = saveShelvesToFile(data, SHELVES_FILE);
    if (result != OK) {
        fprintf(stderr, "保存货架数据失败，错误码: %d\n", result);
        return result;
    }

    // 4. 保存通知数据
    result = saveNotificationsToFile(data, NOTIFICATIONS_FILE);
    if (result != OK) {
        fprintf(stderr, "保存通知数据失败，错误码: %d\n", result);
        return result;
    }

    // 5. 保存日志数据
    result = saveLogsToFile(data, LOGS_FILE);
    if (result != OK) {
        fprintf(stderr, "保存日志数据失败，错误码: %d\n", result);
        return result;
    }

    // 记录数据保存操作
    Log* saveLog = (Log*)malloc(sizeof(Log));
    if (saveLog != NULL) {
        strcpy(saveLog->username, "SYSTEM");

        time_t endTime = time(NULL);
        double elapsed = difftime(endTime, startTime);

        snprintf(saveLog->operation, MAX_DESCRIPTION_LEN,
            "系统数据保存完成，耗时: %.2f 秒", elapsed);

        saveLog->operationTime = endTime;
        saveLog->next = data->logList;
        data->logList = saveLog;

        // 立即保存更新后的日志
        saveLogsToFile(data, LOGS_FILE);
    }

    return OK;
}

/**
 * 释放系统所有内存资源
 *
 * @param data 系统数据结构指针
 */
void cleanupSystem(SystemData* data) {
    if (data == NULL) {
        return;
    }

    // 释放用户链表
    User* currentUser = data->userList;
    User* nextUser = NULL;

    while (currentUser != NULL) {
        nextUser = currentUser->next;
        free(currentUser);
        currentUser = nextUser;
    }

    // 释放包裹链表
    Package* currentPackage = data->packageList;
    Package* nextPackage = NULL;

    while (currentPackage != NULL) {
        nextPackage = currentPackage->next;
        free(currentPackage);
        currentPackage = nextPackage;
    }

    // 释放货架链表
    Shelf* currentShelf = data->shelfList;
    Shelf* nextShelf = NULL;

    while (currentShelf != NULL) {
        nextShelf = currentShelf->next;
        free(currentShelf);
        currentShelf = nextShelf;
    }

    //释放通知链表
    Notification* currentNotification = data->notificationList;
    Notification* nextNotification = NULL;

    while (currentNotification != NULL) {
        nextNotification = currentNotification->next;
        free(currentNotification);
        currentNotification = nextNotification;
    }

    // 释放日志链表
    Log* currentLog = data->logList;
    Log* nextLog = NULL;

    while (currentLog != NULL) {
        nextLog = currentLog->next;
        free(currentLog);
        currentLog = nextLog;
    }

    // 最后释放系统数据结构本身
    free(data);
}

/**
 * 如果数据目录不存在，则创建该目录
 *
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode createDataDirectoryIfNotExists() {
    // 检查目录是否存在
    struct stat st;
    if (stat(DATA_DIR, &st) == 0) {
        // 目录已存在
        return OK;
    }

    // 创建目录
    if (mkdir(DATA_DIR) != 0) {
        return ERR_SYSTEM;
    }

    return OK;
}

/**
 * 如果文件不存在，则创建空文件
 *
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode createEmptyFileIfNotExists(const char* filePath) {
    FILE* file = fopen(filePath, "r");
    if (file != NULL) {
        // 文件已存在
        fclose(file);
        return OK;
    }

    // 创建文件
    file = fopen(filePath, "w");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 根据文件类型写入CSV标题行
    if (strcmp(filePath, USERS_FILE) == 0) {
        fprintf(file, "username,password,phone,address,type,vipLevel,permissions\n");
    }
    else if (strcmp(filePath, PACKAGES_FILE) == 0) {
        fprintf(file, "orderId,receiverPhone,senderPhone,sendername,description,type,status,"
            "pickupCode,receiveTime,notifyTime,pickupTime,weight,fee,pickedUpByPhone,"
            "pickedUpByUsername,isProxyPickup,proxyRelation,expressmanPhone\n");
    }
    else if (strcmp(filePath, SHELVES_FILE) == 0) {
        fprintf(file, "code,capacity1,capacity2,capacity3,occupied1,occupied2,occupied3,"
            "supportType1,supportType2,supportType3,supportType4,supportType5,supportType6,"
            "isSpecialized,codeCounter1,codeCounter2,codeCounter3\n");
    }
    else if (strcmp(filePath, LOGS_FILE) == 0) {
        fprintf(file, "username,operation,operationTime\n");
    }
    else if (strcmp(filePath, NOTIFICATIONS_FILE) == 0) {
        fprintf(file, "notificationID,receiverPhone,message,createTime,notificationType,isRead\n");
    }

    fclose(file);
    return OK;
}

/**
 * 转义CSV字符串，处理逗号、引号等特殊字符
 *
 * @param str 原始字符串
 * @return 转义后的字符串，使用后需要手动释放
 */
char* escapeCSV(const char* str) {
    if (str == NULL) {
        return strdup("");
    }

    // 计算需要的缓冲区大小
    size_t len = strlen(str);
    size_t escLen = len * 2 + 3;  // 最坏情况：每个字符都需要转义，再加上引号和结束符

    char* escaped = (char*)malloc(escLen);
    if (escaped == NULL) {
        return NULL;
    }

    // 检查是否需要转义
    int needQuotes = 0;
    for (size_t i = 0; i < len; i++) {
        if (str[i] == ',' || str[i] == '"' || str[i] == '\n' || str[i] == '\r') {
            needQuotes = 1;
            break;
        }
    }

    if (!needQuotes) {
        // 不需要转义，直接复制
        strcpy(escaped, str);
        return escaped;
    }

    // 需要转义，添加引号并处理内部引号
    size_t j = 0;
    escaped[j++] = '"';

    for (size_t i = 0; i < len; i++) {
        if (str[i] == '"') {
            // 将一个引号变成两个引号
            escaped[j++] = '"';
            escaped[j++] = '"';
        }
        else {
            escaped[j++] = str[i];
        }
    }

    escaped[j++] = '"';
    escaped[j] = '\0';

    return escaped;
}

/**
 * 反转义CSV字符串
 *
 * @param str 转义后的字符串
 * @return 原始字符串，使用后需要手动释放
 */
char* unescapeCSV(const char* str) {
    if (str == NULL) {
        return strdup("");
    }

    size_t len = strlen(str);
    char* unescaped = (char*)malloc(len + 1);
    if (unescaped == NULL) {
        return NULL;
    }

    // 检查是否是引号包围的字符串
    if (len >= 2 && str[0] == '"' && str[len - 1] == '"') {
        size_t j = 0;

        // 跳过开头的引号
        for (size_t i = 1; i < len - 1; i++) {
            if (str[i] == '"' && str[i + 1] == '"') {
                // 两个连续的引号转换为一个引号
                unescaped[j++] = '"';
                i++;  // 跳过第二个引号
            }
            else {
                unescaped[j++] = str[i];
            }
        }

        unescaped[j] = '\0';
    }
    else {
        // 不是引号包围的，直接复制
        strcpy(unescaped, str);
    }

    return unescaped;
}

/**
 * 去除字符串首尾的空白字符
 *
 * @param str 要处理的字符串
 */
void trimString(char* str) {
    if (str == NULL) {
        return;
    }

    size_t len = strlen(str);
    if (len == 0) {
        return;
    }

    // 去除尾部空白
    size_t end = len - 1;
    while (end > 0 && isspace((unsigned char)str[end])) {
        str[end--] = '\0';
    }

    // 去除首部空白
    size_t start = 0;
    while (str[start] != '\0' && isspace((unsigned char)str[start])) {
        start++;
    }

    if (start > 0) {
        // 移动字符串
        memmove(str, str + start, len - start + 1);
    }
}

/**
 * 分割CSV行为字段数组
 *
 * @param line CSV行
 * @param fieldCount 输出参数，返回字段数量
 * @return 字段数组，使用后需要调用freeCSVFields释放
 */
char** splitCSVLine(char* line, int* fieldCount) {
    if (line == NULL || fieldCount == NULL) {
        return NULL;
    }

    *fieldCount = 0;
    size_t len = strlen(line);

    // 预先计算字段数量以分配数组
    size_t maxFields = 1;
    for (size_t i = 0; i < len; i++) {
        if (line[i] == ',') {
            maxFields++;
        }
    }

    char** fields = (char**)malloc(maxFields * sizeof(char*));
    if (fields == NULL) {
        return NULL;
    }

    // 分割字符串
    size_t fieldStart = 0;
    size_t fieldEnd = 0;
    int inQuotes = 0;
    int fieldIndex = 0;

    for (size_t i = 0; i <= len; i++) {
        if (i == len || (line[i] == ',' && !inQuotes)) {
            // 找到字段边界
            fieldEnd = i;
            size_t fieldLen = fieldEnd - fieldStart;

            // 创建字段字符串
            char* fieldStr = (char*)malloc(fieldLen + 1);
            if (fieldStr == NULL) {
                // 释放已分配的内存
                for (int j = 0; j < fieldIndex; j++) {
                    free(fields[j]);
                }
                free(fields);
                return NULL;
            }

            strncpy(fieldStr, line + fieldStart, fieldLen);
            fieldStr[fieldLen] = '\0';

            // 处理引号
            if (fieldLen >= 2 && fieldStr[0] == '"' && fieldStr[fieldLen - 1] == '"') {
                // 去除外部引号
                char* unquoted = (char*)malloc(fieldLen - 1);
                if (unquoted == NULL) {
                    free(fieldStr);
                    for (int j = 0; j < fieldIndex; j++) {
                        free(fields[j]);
                    }
                    free(fields);
                    return NULL;
                }

                strncpy(unquoted, fieldStr + 1, fieldLen - 2);
                unquoted[fieldLen - 2] = '\0';

                // 处理内部双引号
                char* processed = unescapeCSV(unquoted);
                free(unquoted);
                free(fieldStr);
                fieldStr = processed;
            }

            trimString(fieldStr);
            fields[fieldIndex++] = fieldStr;

            fieldStart = i + 1;
        }
        else if (line[i] == '"') {
            // 切换引号状态
            inQuotes = !inQuotes;
        }
    }

    *fieldCount = fieldIndex;
    return fields;
}

/**
 * 释放CSV字段数组
 *
 * @param fields 字段数组
 * @param fieldCount 字段数量
 */
void freeCSVFields(char** fields, int fieldCount) {
    if (fields == NULL) {
        return;
    }

    for (int i = 0; i < fieldCount; i++) {
        free(fields[i]);
    }

    free(fields);
}

/**
 * 写入CSV行
 *
 * @param file 文件指针
 * @param fields 字段数组
 * @param fieldCount 字段数量
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode writeCSVLine(FILE* file, char** fields, int fieldCount) {
    if (file == NULL || fields == NULL || fieldCount <= 0) {
        return ERR_INVALID_PARAM;
    }

    for (int i = 0; i < fieldCount; i++) {
        char* escaped = escapeCSV(fields[i]);
        if (escaped == NULL) {
            return ERR_MEMORY;
        }

        fprintf(file, "%s", escaped);
        free(escaped);

        if (i < fieldCount - 1) {
            fprintf(file, ",");
        }
    }

    fprintf(file, "\n");
    return OK;
}

/**
 * 保存用户数据到文件
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode saveUsersToFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "w");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 写入标题行
    fprintf(file, "username,password,phone,address,type,vipLevel,permissions\n");

    // 写入用户数据
    User* currentUser = data->userList;
    while (currentUser != NULL) {
        char typeStr[10];
        sprintf(typeStr, "%d", currentUser->type);

        char vipLevelStr[10];
        sprintf(vipLevelStr, "%d", currentUser->vipLevel);

        char permissionsStr[10];
        sprintf(permissionsStr, "%u", currentUser->permissions);

        char* fields[] = {
            currentUser->username,
            currentUser->password,
            currentUser->phone,
            currentUser->address,
            typeStr,
            vipLevelStr,
            permissionsStr
        };

        ErrorCode result = writeCSVLine(file, fields, 7);
        if (result != OK) {
            fclose(file);
            return result;
        }

        currentUser = currentUser->next;
    }

    fclose(file);
    return OK;
}

/**
 * 保存包裹数据到文件
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode savePackagesToFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "w");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 写入标题行
    fprintf(file, "orderId,receiverPhone,senderPhone,sendername,description,type,status,"
        "pickupCode,receiveTime,notifyTime,pickupTime,weight,fee,pickedUpByPhone,"
        "pickedUpByUsername,isProxyPickup,proxyRelation,expressmanPhone\n");

    // 写入包裹数据
    Package* currentPackage = data->packageList;
    while (currentPackage != NULL) {
        char typeStr[10];
        sprintf(typeStr, "%d", currentPackage->type);

        char statusStr[10];
        sprintf(statusStr, "%d", currentPackage->status);

        char weightStr[20];
        sprintf(weightStr, "%.2f", currentPackage->weight);

        char feeStr[20];
        sprintf(feeStr, "%.2f", currentPackage->fee);

        char isProxyPickupStr[5];
        sprintf(isProxyPickupStr, "%d", currentPackage->isProxyPickup);

        char* fields[] = {
            currentPackage->orderId,
            currentPackage->receiverPhone,
            currentPackage->senderPhone,
            currentPackage->sendername,
            currentPackage->description,
            typeStr,
            statusStr,
            currentPackage->pickupCode,
            currentPackage->receiveTime,
            currentPackage->notifyTime,
            currentPackage->pickupTime,
            weightStr,
            feeStr,
            currentPackage->pickedUpByPhone,
            currentPackage->pickedUpByUsername,
            isProxyPickupStr,
            currentPackage->proxyRelation,
            currentPackage->expressmanPhone
        };

        ErrorCode result = writeCSVLine(file, fields, 18);
        if (result != OK) {
            fclose(file);
            return result;
        }

        currentPackage = currentPackage->next;
    }

    fclose(file);
    return OK;
}

/**
 * 保存货架数据到文件
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode saveShelvesToFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "w");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 写入标题行
    fprintf(file, "code,capacity1,capacity2,capacity3,occupied1,occupied2,occupied3,"
        "supportType1,supportType2,supportType3,supportType4,supportType5,supportType6,"
        "isSpecialized,codeCounter1,codeCounter2,codeCounter3\n");

    // 写入货架数据
    Shelf* currentShelf = data->shelfList;
    while (currentShelf != NULL) {
        char capacity1Str[10], capacity2Str[10], capacity3Str[10];
        sprintf(capacity1Str, "%d", currentShelf->capacity[0]);
        sprintf(capacity2Str, "%d", currentShelf->capacity[1]);
        sprintf(capacity3Str, "%d", currentShelf->capacity[2]);

        char occupied1Str[10], occupied2Str[10], occupied3Str[10];
        sprintf(occupied1Str, "%d", currentShelf->occupied[0]);
        sprintf(occupied2Str, "%d", currentShelf->occupied[1]);
        sprintf(occupied3Str, "%d", currentShelf->occupied[2]);

        char supportType1Str[5], supportType2Str[5], supportType3Str[5],
            supportType4Str[5], supportType5Str[5], supportType6Str[5];
        sprintf(supportType1Str, "%d", currentShelf->supportTypes[0]);
        sprintf(supportType2Str, "%d", currentShelf->supportTypes[1]);
        sprintf(supportType3Str, "%d", currentShelf->supportTypes[2]);
        sprintf(supportType4Str, "%d", currentShelf->supportTypes[3]);
        sprintf(supportType5Str, "%d", currentShelf->supportTypes[4]);
        sprintf(supportType6Str, "%d", currentShelf->supportTypes[5]);

        char isSpecializedStr[5];
        sprintf(isSpecializedStr, "%d", currentShelf->isSpecialized);

        char codeCounter1Str[10], codeCounter2Str[10], codeCounter3Str[10];
        sprintf(codeCounter1Str, "%d", currentShelf->codeCounter[0]);
        sprintf(codeCounter2Str, "%d", currentShelf->codeCounter[1]);
        sprintf(codeCounter3Str, "%d", currentShelf->codeCounter[2]);

        char* fields[] = {
            currentShelf->code,
            capacity1Str,
            capacity2Str,
            capacity3Str,
            occupied1Str,
            occupied2Str,
            occupied3Str,
            supportType1Str,
            supportType2Str,
            supportType3Str,
            supportType4Str,
            supportType5Str,
            supportType6Str,
            isSpecializedStr,
            codeCounter1Str,
            codeCounter2Str,
            codeCounter3Str
        };

        ErrorCode result = writeCSVLine(file, fields, 17);
        if (result != OK) {
            fclose(file);
            return result;
        }

        currentShelf = currentShelf->next;
    }

    fclose(file);
    return OK;
}

/**
 * 保存日志数据到文件
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode saveLogsToFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "w");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 写入标题行
    fprintf(file, "username,operation,operationTime\n");

    // 写入日志数据
    Log* currentLog = data->logList;
    while (currentLog != NULL) {
        char timeStr[30];
        sprintf(timeStr, "%lld", (long long)currentLog->operationTime);

        char* fields[] = {
            currentLog->username,
            currentLog->operation,
            timeStr
        };

        ErrorCode result = writeCSVLine(file, fields, 3);
        if (result != OK) {
            fclose(file);
            return result;
        }

        currentLog = currentLog->next;
    }

    fclose(file);
    return OK;
}

/**
 * 保存通知数据到文件
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode saveNotificationsToFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "w");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 写入标题行
    fprintf(file, "notificationID,receiverPhone,message,createTime,notificationType,isRead\n");

    // 遍历所有用户的通知链表
    User* currentUser = data->userList;
    while (currentUser != NULL) {
        Notification* currentNotification = data->notificationList;

        while (currentNotification != NULL && (strcmp(currentNotification->receiverPhone, currentUser->phone) == 0)) {
            char timeStr[30];
            sprintf(timeStr, "%lld", (long long)currentNotification->createTime);

            char typeStr[10];
            sprintf(typeStr, "%d", currentNotification->notificationType);

            char isReadStr[5];
            sprintf(isReadStr, "%d", currentNotification->isRead);

            char* fields[] = {
                currentNotification->notificationID,
                currentNotification->receiverPhone,
                currentNotification->message,
                timeStr,
                typeStr,
                isReadStr
            };

            ErrorCode result = writeCSVLine(file, fields, 6);
            if (result != OK) {
                fclose(file);
                return result;
            }

            currentNotification = currentNotification->next;
        }

        currentUser = currentUser->next;
    }

    fclose(file);
    return OK;
}

/**
 * 从文件加载用户数据
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode loadUsersFromFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "r");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 清空现有用户链表
    User* currentUser = data->userList;
    while (currentUser != NULL) {
        User* next = currentUser->next;
        free(currentUser);
        currentUser = next;
    }
    data->userList = NULL;

    // 读取标题行
    char line[1024];
    if (fgets(line, sizeof(line), file) == NULL) {
        fclose(file);
        return OK;  // 空文件，只有标题行
    }

    // 逐行读取用户数据
    User* lastUser = NULL;
    while (fgets(line, sizeof(line), file) != NULL) {
        // 去除行尾的换行符
        size_t len = strlen(line);
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }

        // 解析CSV行
        int fieldCount;
        char** fields = splitCSVLine(line, &fieldCount);
        if (fields == NULL) {
            fclose(file);
            return ERR_MEMORY;
        }

        if (fieldCount != 7) {
            freeCSVFields(fields, fieldCount);
            continue;  // 跳过格式不正确的行
        }

        // 创建新用户
        User* newUser = (User*)malloc(sizeof(User));
        if (newUser == NULL) {
            freeCSVFields(fields, fieldCount);
            fclose(file);
            return ERR_MEMORY;
        }

        // 填充用户字段
        strncpy(newUser->username, fields[0], MAX_USERNAME_LEN);
        strncpy(newUser->password, fields[1], MAX_PASSWORD_LEN);
        strncpy(newUser->phone, fields[2], MAX_PHONE_LEN);
        strncpy(newUser->address, fields[3], MAX_ADDRESS_LEN);
        newUser->type = (UserType)atoi(fields[4]);
        newUser->vipLevel = atoi(fields[5]);
        newUser->permissions = (unsigned int)strtoul(fields[6], NULL, 10);

        newUser->next = NULL;

        // 添加到链表
        if (lastUser == NULL) {
            data->userList = newUser;
        }
        else {
            lastUser->next = newUser;
        }
        lastUser = newUser;

        freeCSVFields(fields, fieldCount);
    }

    fclose(file);
    return OK;
}

/**
 * 从文件加载包裹数据
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode loadPackagesFromFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "r");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 清空现有包裹链表
    Package* currentPackage = data->packageList;
    while (currentPackage != NULL) {
        Package* next = currentPackage->next;
        free(currentPackage);
        currentPackage = next;
    }
    data->packageList = NULL;
    data->packageTail = NULL;

    // 读取标题行
    char line[1024];
    if (fgets(line, sizeof(line), file) == NULL) {
        fclose(file);
        return OK;  // 空文件，只有标题行
    }

    // 逐行读取包裹数据
    Package* lastPackage = NULL;
    while (fgets(line, sizeof(line), file) != NULL) {
        // 去除行尾的换行符
        size_t len = strlen(line);
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }

        // 解析CSV行
        int fieldCount;
        char** fields = splitCSVLine(line, &fieldCount);
        if (fields == NULL) {
            fclose(file);
            return ERR_MEMORY;
        }

        if (fieldCount != 18) {
            freeCSVFields(fields, fieldCount);
            continue;  // 跳过格式不正确的行
        }

        // 创建新包裹
        Package* newPackage = (Package*)malloc(sizeof(Package));
        if (newPackage == NULL) {
            freeCSVFields(fields, fieldCount);
            fclose(file);
            return ERR_MEMORY;
        }

        // 填充包裹字段
        strncpy(newPackage->orderId, fields[0], MAX_ORDER_ID_LEN);
        strncpy(newPackage->receiverPhone, fields[1], MAX_PHONE_LEN);
        strncpy(newPackage->senderPhone, fields[2], MAX_PHONE_LEN);
        strncpy(newPackage->sendername, fields[3], MAX_USERNAME_LEN);
        strncpy(newPackage->description, fields[4], MAX_DESCRIPTION_LEN);
        newPackage->type = (PackageType)atoi(fields[5]);
        newPackage->status = (PackageStatus)atoi(fields[6]);
        strncpy(newPackage->pickupCode, fields[7], MAX_PICKUP_CODE_LEN);
        strncpy(newPackage->receiveTime, fields[8], 64);
        strncpy(newPackage->notifyTime, fields[9], 64);
        strncpy(newPackage->pickupTime, fields[10], 64);
        newPackage->weight = (float)atof(fields[11]);
        newPackage->fee = (float)atof(fields[12]);
        strncpy(newPackage->pickedUpByPhone, fields[13], MAX_PHONE_LEN);
        strncpy(newPackage->pickedUpByUsername, fields[14], MAX_USERNAME_LEN);
        newPackage->isProxyPickup = atoi(fields[15]);
        strncpy(newPackage->proxyRelation, fields[16], MAX_DESCRIPTION_LEN);
        strncpy(newPackage->expressmanPhone, fields[17], MAX_PHONE_LEN);

        newPackage->next = NULL;

        // 添加到链表
        if (lastPackage == NULL) {
            data->packageList = newPackage;
        }
        else {
            lastPackage->next = newPackage;
        }
        lastPackage = newPackage;
        data->packageTail = newPackage;

        freeCSVFields(fields, fieldCount);
    }

    fclose(file);
    return OK;
}

/**
 * 从文件加载货架数据
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode loadShelvesFromFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "r");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 清空现有货架链表
    Shelf* currentShelf = data->shelfList;
    while (currentShelf != NULL) {
        Shelf* next = currentShelf->next;
        free(currentShelf);
        currentShelf = next;
    }
    data->shelfList = NULL;
    data->shelfTail = NULL;

    // 读取标题行
    char line[1024];
    if (fgets(line, sizeof(line), file) == NULL) {
        fclose(file);
        return OK;  // 空文件，只有标题行
    }

    // 逐行读取货架数据
    Shelf* lastShelf = NULL;
    while (fgets(line, sizeof(line), file) != NULL) {
        // 去除行尾的换行符
        size_t len = strlen(line);
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }

        // 解析CSV行
        int fieldCount;
        char** fields = splitCSVLine(line, &fieldCount);
        if (fields == NULL) {
            fclose(file);
            return ERR_MEMORY;
        }

        if (fieldCount != 17) {
            freeCSVFields(fields, fieldCount);
            continue;  // 跳过格式不正确的行
        }

        // 创建新货架
        Shelf* newShelf = (Shelf*)malloc(sizeof(Shelf));
        if (newShelf == NULL) {
            freeCSVFields(fields, fieldCount);
            fclose(file);
            return ERR_MEMORY;
        }

        // 填充货架字段
        strncpy(newShelf->code, fields[0], MAX_SHELF_CODE_LEN);

        // 容量字段
        newShelf->capacity[0] = atoi(fields[1]);
        newShelf->capacity[1] = atoi(fields[2]);
        newShelf->capacity[2] = atoi(fields[3]);

        // 已占用字段
        newShelf->occupied[0] = atoi(fields[4]);
        newShelf->occupied[1] = atoi(fields[5]);
        newShelf->occupied[2] = atoi(fields[6]);

        // 支持的包裹类型字段
        newShelf->supportTypes[0] = atoi(fields[7]);
        newShelf->supportTypes[1] = atoi(fields[8]);
        newShelf->supportTypes[2] = atoi(fields[9]);
        newShelf->supportTypes[3] = atoi(fields[10]);
        newShelf->supportTypes[4] = atoi(fields[11]);
        newShelf->supportTypes[5] = atoi(fields[12]);

        // 专用货架标志
        newShelf->isSpecialized = atoi(fields[13]);

        // 取件码计数器
        newShelf->codeCounter[0] = atoi(fields[14]);
        newShelf->codeCounter[1] = atoi(fields[15]);
        newShelf->codeCounter[2] = atoi(fields[16]);

        newShelf->next = NULL;

        // 添加到链表
        if (lastShelf == NULL) {
            data->shelfList = newShelf;
        }
        else {
            lastShelf->next = newShelf;
        }
        lastShelf = newShelf;
        data->shelfTail = newShelf;

        freeCSVFields(fields, fieldCount);
    }

    fclose(file);
    return OK;
}

/**
 * 从文件加载日志数据
 *
 * @param data 系统数据
 * @param filePath 文件路径
 * @return 成功返回OK，失败返回错误码
 */
ErrorCode loadLogsFromFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "r");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 清空现有日志链表
    Log* currentLog = data->logList;
    while (currentLog != NULL) {
        Log* next = currentLog->next;
        free(currentLog);
        currentLog = next;
    }
    data->logList = NULL;

    // 读取标题行
    char line[1024];
    if (fgets(line, sizeof(line), file) == NULL) {
        fclose(file);
        return OK;  // 空文件，只有标题行
    }

    // 逐行读取日志数据
    Log* lastLog = NULL;
    while (fgets(line, sizeof(line), file) != NULL) {
        // 去除行尾的换行符
        size_t len = strlen(line);
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }

        // 解析CSV行
        int fieldCount;
        char** fields = splitCSVLine(line, &fieldCount);
        if (fields == NULL) {
            fclose(file);
            return ERR_MEMORY;
        }

        if (fieldCount != 3) {
            freeCSVFields(fields, fieldCount);
            continue;  // 跳过格式不正确的行
        }

        // 创建新日志
        Log* newLog = (Log*)malloc(sizeof(Log));
        if (newLog == NULL) {
            freeCSVFields(fields, fieldCount);
            fclose(file);
            return ERR_MEMORY;
        }

        // 填充日志字段
        strncpy(newLog->username, fields[0], MAX_USERNAME_LEN);
        strncpy(newLog->operation, fields[1], MAX_DESCRIPTION_LEN);
        newLog->operationTime = (time_t)strtoll(fields[2], NULL, 10);

        newLog->next = NULL;

        // 添加到链表（头插法，使最新的日志在前面）
        if (data->logList == NULL) {
            data->logList = newLog;
        }
        else {
            newLog->next = data->logList;
            data->logList = newLog;
        }

        freeCSVFields(fields, fieldCount);
    }

    fclose(file);
    return OK;
}

static ErrorCode loadNotificationsFromFile(SystemData* data, const char* filePath) {
    if (data == NULL || filePath == NULL) {
        return ERR_INVALID_PARAM;
    }

    FILE* file = fopen(filePath, "r");
    if (file == NULL) {
        return ERR_FILE_IO;
    }

    // 清空系统当前的通知链表
    
    Notification* currentNotification = data->notificationList;
    while (currentNotification != NULL) {
        Notification* next = currentNotification->next;
        free(currentNotification);
        currentNotification = next;
    }
    data->notificationList = NULL;  // 重置系统通知链表为空

    // 读取标题行
    char line[1024];
    if (fgets(line, sizeof(line), file) == NULL) {
        fclose(file);
        return OK;  // 空文件，只有标题行
    }

    // 逐行读取通知数据
    Notification* lastNotification = NULL;
    while (fgets(line, sizeof(line), file) != NULL) {
        // 去除行尾的换行符
        size_t len = strlen(line);
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[--len] = '\0';
        }

        // 解析CSV行
        int fieldCount;
        char** fields = splitCSVLine(line, &fieldCount);
        if (fields == NULL) {
            fclose(file);
            return ERR_MEMORY;
        }

        if (fieldCount != 6) {  // 假设通知有6个字段
            freeCSVFields(fields, fieldCount);
            continue;  // 跳过格式不正确的行
        }

        // 创建新通知
        Notification* newNotification = (Notification*)malloc(sizeof(Notification));
        if (newNotification == NULL) {
            freeCSVFields(fields, fieldCount);
            fclose(file);
            return ERR_MEMORY;
        }

        // 填充通知字段
        strncpy(newNotification->notificationID, fields[0], MAX_NOTIFICATION_ID_LEN);
        strncpy(newNotification->receiverPhone, fields[1], MAX_PHONE_LEN);
        strncpy(newNotification->message, fields[2], MAX_DESCRIPTION_LEN);
        newNotification->createTime = (time_t)strtoll(fields[3], NULL, 10);
        newNotification->notificationType = atoi(fields[4]);
        newNotification->isRead = atoi(fields[5]);

        newNotification->next = NULL;

        // 添加到通知链表
        if (data->notificationList == NULL) {
            data->notificationList = newNotification;
        }
        else {
            lastNotification->next = newNotification;
        }
        lastNotification = newNotification;

        freeCSVFields(fields, fieldCount);
    }

    fclose(file);
    return OK;
}

int hasPermission(User* user, unsigned int requiredPermission) {
    if (user == NULL) {
        return 0;
    }
    return (user->type == USER_ADMIN);
}